package com.stone;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGL10;




import android.app.Activity;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;

/**
 * 在Android中，可以直接支持3D图形的绘制，主要使用OpenGL标准的类
 * javax.microedition.khronos.egl但是需要结合Android GUI系统使用。
 * 在使用3D图形API的主要步骤，通常如下：
 * 1、扩展android.opengl.GLSurfaceView类
 * 2、扩展实现android.opengl.GLSurfaceView中的Renderer(渲染器)
 * 3、实现GLSurfaceView中的onDrawFrame等函数。
 * android.opengl.GLSurfaceView扩展了android.view.SurfaceView，android.view.SurfaceView
 * 扩展了android.view.View，因此GLSurfaceView本身可以作为android.view.View来使用。
 * GLSurfaceView中的内部类Renderer是一个接口，其中定义了以下几个方法：
 * abstract void onDrawFrame(GL10 g1)//绘制当前帧
 * abstract void onSurfaceChanged(GL10 g1,int width,int height)//surface变化时调用
 * abstrace void onSurfaceCreated(GL10 g1,EGLConfig config)//surface创建时候调用
 * 方法中的参数GL10是javax.microedition.khronos.egl包中的通用函数。
 * GLSurfaceView：Renderer中的onSurfaceChanged()和onSurfaceCreate()方法实际上和SurfaceView
 * 中的两个方法相对应。
 * */
public class OpenGLDemo extends Activity{
	  @Override
	    protected void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);

	        // Create our Preview view and set it as the content of our
	        // Activity
	        mGLSurfaceView = new TouchSurfaceView(this);
	        setContentView(mGLSurfaceView);
	        mGLSurfaceView.requestFocus();
	        mGLSurfaceView.setFocusableInTouchMode(true);
	    }

	    @Override
	    protected void onResume() {
	        // Ideally a game should implement onResume() and onPause()
	        // to take appropriate action when the activity looses focus
	        super.onResume();
	        mGLSurfaceView.onResume();
	    }

	    @Override
	    protected void onPause() {
	        // Ideally a game should implement onResume() and onPause()
	        // to take appropriate action when the activity looses focus
	        super.onPause();
	        mGLSurfaceView.onPause();
	    }

	    private GLSurfaceView mGLSurfaceView;
	}

	/**
	 * Implement a simple rotation control.
	 *
	 */
	class TouchSurfaceView extends GLSurfaceView {

	    public TouchSurfaceView(Context context) {
	        super(context);
	        mRenderer = new CubeRenderer();
	        setRenderer(mRenderer);
	        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
	    }

	    @Override public boolean onTrackballEvent(MotionEvent e) {
	        mRenderer.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR;
	        mRenderer.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR;
	        requestRender();
	        return true;
	    }

	    @Override public boolean onTouchEvent(MotionEvent e) {
	        float x = e.getX();
	        float y = e.getY();
	        switch (e.getAction()) {
	        case MotionEvent.ACTION_MOVE:
	            float dx = x - mPreviousX;
	            float dy = y - mPreviousY;
	            mRenderer.mAngleX += dx * TOUCH_SCALE_FACTOR;
	            mRenderer.mAngleY += dy * TOUCH_SCALE_FACTOR;
	            requestRender();
	        }
	        mPreviousX = x;
	        mPreviousY = y;
	        return true;
	    }

	    /**
	     * Render a cube.
	     */
	    private class CubeRenderer implements GLSurfaceView.Renderer {
	        public CubeRenderer() {
	            mCube = new Cube();
	        }

	        public void onDrawFrame(GL10 gl) {
	            /*
	             * Usually, the first thing one might want to do is to clear
	             * the screen. The most efficient way of doing this is to use
	             * glClear().
	             */

	            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

	            /*
	             * Now we're ready to draw some 3D objects
	             */

	            gl.glMatrixMode(GL10.GL_MODELVIEW);
	            gl.glLoadIdentity();
	            gl.glTranslatef(0, 0, -3.0f);
	            gl.glRotatef(mAngleX, 0, 1, 0);
	            gl.glRotatef(mAngleY, 1, 0, 0);

	            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
	            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

	            mCube.draw(gl);
	        }

	        public int[] getConfigSpec() {
	            // We want a depth buffer, don't care about the
	            // details of the color buffer.
	            int[] configSpec = {
	                    EGL10.EGL_DEPTH_SIZE,   16,
	                    EGL10.EGL_NONE
	            };
	            return configSpec;
	        }

	        public void onSurfaceChanged(GL10 gl, int width, int height) {
	             gl.glViewport(0, 0, width, height);

	             /*
	              * Set our projection matrix. This doesn't have to be done
	              * each time we draw, but usually a new projection needs to
	              * be set when the viewport is resized.
	              */

	             float ratio = (float) width / height;
	             gl.glMatrixMode(GL10.GL_PROJECTION);
	             gl.glLoadIdentity();
	             gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
	        }

	        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
	            /*
	             * By default, OpenGL enables features that improve quality
	             * but reduce performance. One might want to tweak that
	             * especially on software renderer.
	             */
	            gl.glDisable(GL10.GL_DITHER);

	            /*
	             * Some one-time OpenGL initialization can be made here
	             * probably based on features of this particular context
	             */
	             gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
	                     GL10.GL_FASTEST);


	             gl.glClearColor(1,1,1,1);
	             gl.glEnable(GL10.GL_CULL_FACE);
	             gl.glShadeModel(GL10.GL_SMOOTH);
	             gl.glEnable(GL10.GL_DEPTH_TEST);
	        }
	        private Cube mCube;
	        public float mAngleX;
	        public float mAngleY;
	    }

	    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
	    private final float TRACKBALL_SCALE_FACTOR = 36.0f;
	    private CubeRenderer mRenderer;
	    private float mPreviousX;
	    private float mPreviousY;
	}


